from fastapi import HTTPException, status, Request
from fastapi.responses import JSONResponse

from app.utils.logger import logger
from app.utils.responses import error_response
from jose import JWTError, jwt
from app.config.settings import settings
from typing import Any
from datetime import datetime


class AuthMiddleware:
    """认证中间件类"""
    
    def __init__(self, app):
        self.app = app
        # 允许访问的路径（无需认证）
        self.public_paths = [
            "/",
            "/api/v1/auth/login",
            "/api/v1/auth/logout",
            "/docs",
            "/redoc",
            "/openapi.json"
        ]

    async def __call__(self, scope, receive, send):
        if scope["type"] != "http":
            await self.app(scope, receive, send)
            return

        request = Request(scope, receive)
        
        # 检查请求路径是否需要认证
        path = request.url.path
        need_auth = True

        for public_path in self.public_paths:
            if path == public_path or path.startswith(public_path + "/") or path.startswith(public_path + "?"):
                need_auth = False
                break

        # 如果需要认证，则检查用户是否已登录
        if need_auth:
            auth_header = request.headers.get("Authorization")
            logger.info(f"Checking authentication for {path} Authorization: {auth_header}")
            if not auth_header:
                # 不直接抛出异常，而是返回统一错误响应
                content = {
                    "code": status.HTTP_401_UNAUTHORIZED,
                    "message": "Not authenticated",
                    "data": None,
                    "timestamp": datetime.utcnow().isoformat() + "Z"
                }
                response = JSONResponse(
                    content=content,
                    status_code=status.HTTP_401_UNAUTHORIZED
                )
                await response(scope, receive, send)
                return

            # 解析token
            try:
                token = auth_header.split(" ")[1]  # Bearer <token>
                payload = jwt.decode(token, settings.secret_key, algorithms=["HS256"])
                user_id: Any = payload.get("sub")
                if user_id is None:
                    content = {
                        "code": status.HTTP_401_UNAUTHORIZED,
                        "message": "Could not validate credentials",
                        "data": None,
                        "timestamp": datetime.utcnow().isoformat() + "Z"
                    }
                    response = JSONResponse(
                        content=content,
                        status_code=status.HTTP_401_UNAUTHORIZED
                    )
                    await response(scope, receive, send)
                    return
            except IndexError:
                content = {
                    "code": status.HTTP_401_UNAUTHORIZED,
                    "message": "Invalid authorization header format",
                    "data": None,
                    "timestamp": datetime.utcnow().isoformat() + "Z"
                }
                response = JSONResponse(
                    content=content,
                    status_code=status.HTTP_401_UNAUTHORIZED
                )
                await response(scope, receive, send)
                return
            except JWTError:
                content = {
                    "code": status.HTTP_401_UNAUTHORIZED,
                    "message": "Could not validate credentials",
                    "data": None,
                    "timestamp": datetime.utcnow().isoformat() + "Z"
                }
                response = JSONResponse(
                    content=content,
                    status_code=status.HTTP_401_UNAUTHORIZED
                )
                await response(scope, receive, send)
                return

        await self.app(scope, receive, send)